home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / xblockbuster / xblockbust.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  10KB  |  388 lines

  1. /*
  2.  * Xblockbuster should run on any X11 system (bw or color) - MSW
  3.  *
  4.  *****************************************************************************
  5.  * Appearance ONLY shamelessly stolen from the real video game,
  6.  * wonderfully written by someone somewhere (I haven't got the foggiest).
  7.  *
  8.  * Move mouse to move pallet and keep the ball on the stage.
  9.  *
  10.  * Stages are built from various building blocks, some of which are based on
  11.  * recollection from analogous blocks in the video game, others, in particular
  12.  * the interesting ones, are new.
  13.  *
  14.  * The stages can be defined from the ascii map codes using any text editor.
  15.  * They must be numbered consecutively from 0 with the total number
  16.  * (i.e., one more than the highest number) available in the file nb_stages.
  17.  *
  18.  * -- Eric Van Gestel (ericvg@cs.kuleuven.ac.be)
  19.  */
  20.  
  21. #include "xblockbuster.h"
  22. #include <dirent.h>
  23. #include <sys/stat.h>
  24. #include <sys/time.h>
  25. #include <signal.h>
  26.  
  27. #include "icons/blockbuster.icon"
  28. #include "patchlevel.h"
  29.  
  30. int timer_active=FALSE,        /* has the user started the ball? */
  31.     window_active=FALSE;    /* is the pointer in the window? */
  32. int time_to_move = 0;
  33.  
  34.  
  35.  
  36. void
  37. time_tick(sig)
  38.   int    sig;
  39. {
  40.     static unsigned short event_count = 0;
  41.  
  42.     time_to_move = 1;
  43. #ifdef INTR_DRAW
  44.     if (timer_active && window_active) {
  45.         move_balls();
  46.         XFlush(display);
  47.     }
  48. #endif /*INTR_DRAW*/
  49. }
  50.  
  51. setup_itimer()
  52. {
  53.     struct sigaction  catch, devnull;
  54.     struct itimerval  interval;
  55.  
  56.     /* Catch SIGALARM reliably */
  57.     catch.sa_handler = time_tick;
  58.     sigemptyset(&catch.sa_mask);
  59.     sigaddset(&catch.sa_mask, SIGALRM);
  60.     catch.sa_flags = 0;
  61.     if (sigaction(SIGALRM, &catch, &devnull) < 0)
  62.         perror("sigaction");
  63.  
  64.     /* ... then set the interval timer */
  65.     interval.it_value.tv_sec = 0;
  66.     interval.it_value.tv_usec = 10000;
  67.     interval.it_interval = interval.it_value;
  68.     if (setitimer(ITIMER_REAL, &interval, (struct itimerval *)NULL) < 0)
  69.         perror("setitimer");
  70. }
  71.  
  72. void event_handler()
  73. {
  74.     XEvent    e;
  75.     int    row,col,sleeptime;
  76.     double    old_pallet_y;
  77.     char    keystr[2],str[10];
  78.  
  79.     setup_itimer();
  80.  
  81.     draw_pallet();
  82.     while (1) {
  83. #ifndef INTR_DRAW
  84.     if (time_to_move && timer_active && window_active) {
  85.         time_to_move = 0;
  86.         move_balls();
  87.     }
  88.  
  89.     // Now, let's wait for an event, or time to move the balls
  90.     {
  91.         int    Xfd;
  92.         fd_set    fds;
  93.  
  94.         Xfd = ConnectionNumber(display);
  95.         FD_ZERO(&fds);
  96.         FD_SET(Xfd, &fds);
  97.         select(Xfd+1, &fds, &fds, &fds, 0);
  98.     }
  99.  
  100.     if (XPending(display))
  101. #endif /*!INTR_DRAW*/
  102.     {
  103.         /* Event handling (if any events need to be handled) - MSW */
  104.         XNextEvent(display, &e);
  105. #ifdef INTR_DRAW
  106.         sighold(SIGALRM);
  107. #endif /*INTR_DRAW*/
  108.         switch (e.type) {
  109.         case ButtonPress:
  110.             switch (e.xbutton.button) {
  111.             case Button3: /* right mouse button */
  112.                 /* Clear message area */
  113.                 XFillRectangle(display, win, gc_erase,
  114.                 0,0,STAGE_WIDTH_IN_PIXELS, MSG_HEIGHT);
  115.                 /* redo messages */
  116.                 XDrawImageString(display, win, gc,
  117.                 OFFSET_SPEED, font_height*2, stage_name,
  118.                 strlen(stage_name));
  119.                 if (score_incr>1) {
  120.                  sprintf(str,"Bonus x%d",score_incr);
  121.                 XDrawImageString(display, win, gc,
  122.                     OFFSET_SCORE, font_height*2, str, 
  123.                     strlen(str));
  124.                 }
  125.                 print_balls();
  126.                 print_score();
  127.                 show_speeds();
  128.                 timer_active=TRUE;
  129.                 move_balls();
  130.                 break;
  131.  
  132.             case Button2:
  133.                 draw_pallet(); /* erase old */
  134.                 pallet_y = (double) (pallet_yI = PALLET_MAX_Y+4);
  135.                 pallet_row = MAX_ROW - 1;
  136.                 draw_pallet(); /* draw new */
  137.                 break;
  138.  
  139.             case Button1:
  140.                 draw_pallet(); /* erase old */
  141.                 if (pallet_yI > PALLET_MIN_Y) {
  142.                     old_pallet_y = pallet_y;
  143.                     pallet_y = (double) (pallet_yI -=16);
  144.                     pallet_row--;
  145.  
  146.                     /* See if the ball could have been
  147.                     deflected as the pallete moved
  148.                     upwards */
  149.                     check_deflections(old_pallet_y);
  150.                 }
  151.                 draw_pallet(); /* draw new */
  152.                 break;
  153.             }
  154.         break;
  155.  
  156.         case KeyPress:
  157.             XLookupString((XKeyEvent*) &e,keystr,2, NULL, NULL);
  158.             if (keystr[0]==27) {    /* Escape to save */
  159.                 if (!ball1.quadrant && !ball2.quadrant &&
  160.                     !ball3.quadrant && last_busted_brick==NULL) {
  161.                     XDrawImageString(display, win, gc,
  162.                     OFFSET_BALLS, font_height,
  163.                     "Saving...             ",
  164.                     23);
  165.                     save();
  166.                     }
  167.                 else
  168.                     XDrawImageString(display, win, gc,
  169.                     OFFSET_BALLS, font_height,
  170.                     "Not Saved...          ",
  171.                     23);
  172.             }
  173.         break;
  174.  
  175.         case MotionNotify:
  176.             draw_pallet();    /* erase old pallet */
  177.             pallet_x = (double) (pallet_xI =e.xmotion.x);
  178.             mouse_yI = e.xmotion.y;
  179.             draw_pallet();    /* draw new one */
  180.             break;
  181.  
  182.         case EnterNotify:
  183.             window_active = TRUE;
  184.             break;
  185.  
  186.         case LeaveNotify:
  187.             window_active = FALSE;
  188.             break;
  189.  
  190.         case Expose:
  191.             /* redraw the stage */
  192.  
  193.             for ( row = 0; row <= MAX_ROW; row++ ) {
  194.                         draw_brick0( row, 0 );
  195.                         for ( col = 1; col < MAX_COL; col++ )
  196.                                 draw_brick( row, col );
  197.                         draw_brick0( row, MAX_COL );
  198.             }
  199.             draw_pallet();
  200.             break;
  201.  
  202.         default:
  203.             printf("unknown event: %d\n",e.type);
  204.             break;
  205.         }
  206. #ifdef INTR_DRAW
  207.         XFlush(display);
  208.         sigrelse(SIGALRM);
  209. #endif /*INTR_DRAW*/
  210.     }
  211.     }
  212. }
  213.  
  214.  
  215. void get_playground( argc, argv )
  216. int argc;
  217. char *argv[];
  218. {
  219.     DIR        *dirp;
  220.     struct dirent    *dp;
  221.     struct stat    st;
  222.     int        len, found;
  223.  
  224.     /* set default playground directory */
  225.     strcpy( playground, STAGEDIR );
  226.     strcat( playground, "/" );
  227.     /* check for additional arguments (specific playground) */
  228.     if ( argc > 1 ) {
  229.         if ( argv[1][0] == '-' ) {
  230.             /* list available playgrounds */
  231.             printf( "available playgrounds are:\n" );
  232.             printf( "\tdefault\n" );
  233.             dirp = opendir(STAGEDIR);
  234.             for( dp=readdir( dirp ); dp!=NULL; dp=readdir( dirp ) ) {
  235.                 if ( !strncmp( dp->d_name, "STAGES.", 7 ) )
  236.                     printf( "\t%s\n", (dp->d_name)+7 );
  237.             }
  238.             closedir( dirp );
  239.             exit( 0 );
  240.         }
  241.         /* it's a playground name or private directory */
  242.         if( !strcmp( argv[1], "default" ) ) {
  243.             /* just in case someone used default */
  244.             strcat( playground, "STAGES" );
  245.             return;
  246.         }
  247.         found = 0;
  248.         len = strlen( argv[1] );
  249.         dirp = opendir( STAGEDIR );
  250.         for( dp=readdir( dirp ); dp!=NULL; dp=readdir( dirp ) ) {
  251.             if ( dp->d_reclen == len+7 &&
  252.                  !strcmp( (dp->d_name)+7, argv[1] ) ) {
  253.                 found++;
  254.                 break;
  255.             }
  256.         }
  257.         closedir( dirp );
  258.         if ( found )
  259.             strcat( playground, dp->d_name );
  260.         else {
  261.             /* private dir */
  262.             strcpy( playground, argv[1] );
  263.             stat( playground, &st );
  264.             if( !(st.st_mode & S_IFDIR) ) {
  265.                 printf( "private playground <%s> not a directory.\n",
  266.                     playground );
  267.                 exit( 1 );
  268.             }
  269.         }
  270.     } else {
  271.         strcat( playground, "STAGES" );
  272.     }
  273. }
  274.                 
  275.  
  276. /*** xblockbuster ***/
  277. void main( argc, argv )
  278.     int             argc;
  279.     char           *argv[];
  280.  
  281. {
  282.     XGCValues    xgcvalues;
  283.     Pixmap        icon_image;
  284.     XSizeHints    size_hints;
  285.     XWMHints    wm_hints;
  286.     XClassHint    class_hints;
  287.     XTextProperty    VersionTextProp;
  288.     static char    *VersionList[2] = { VERSION, 0 };
  289.  
  290.     /* who am i ? ['cuserid(3S)' is fooled by 'su(1)'] */
  291.     login = getpwuid( getuid(  ) )->pw_name;
  292.  
  293.     if ((display=XOpenDisplay(NULL))==NULL) {
  294.         fprintf(stderr, "Unable to open display: %s\n",
  295.             XDisplayName(NULL));
  296.         exit(1);
  297.     }
  298.     //(void) XSynchronize(display, 1);  // For DEBUGGING
  299.     screen_num = DefaultScreen(display);
  300.     win = XCreateSimpleWindow(display, RootWindow(display, screen_num),
  301.         0, 0, STAGE_WIDTH_IN_PIXELS, STAGE_HEIGHT_IN_PIXELS,
  302.         0, 2, WhitePixel(display, screen_num));
  303.  
  304.  
  305.     XSelectInput(display, win, ExposureMask | ButtonPressMask |
  306.         LeaveWindowMask | EnterWindowMask | KeyPressMask |
  307.         PointerMotionMask);
  308.  
  309.  
  310.     if ((font_info = XLoadQueryFont(display, FONT))==NULL) {
  311.         fprintf(stderr,"Unable to load font %s\n",FONT);
  312.         exit(1);
  313.     }
  314.     font_width= font_info->max_bounds.rbearing - font_info->min_bounds.lbearing;
  315.     font_height=font_info->max_bounds.ascent + font_info->max_bounds.descent +1;
  316.  
  317.  
  318.     xgcvalues.foreground = BlackPixel(display, screen_num);
  319.     xgcvalues.background = WhitePixel(display, screen_num);
  320.     xgcvalues.graphics_exposures = False;
  321.     xgcvalues.font = font_info->fid;
  322.  
  323.     /* create the various graphic contexts we need. gc and gc_color
  324.     differ only in the we only change the colors on the gc_color context,
  325.     and thus, it is only used for brick drawing.  gc_color really has no
  326.     use on a black & white system */
  327.  
  328.     gc = XCreateGC(display, win, GCFont | 
  329.         GCForeground | GCBackground | GCGraphicsExposures, &xgcvalues);
  330.     gc_color = XCreateGC(display, win, GCFont | 
  331.         GCForeground | GCBackground | GCGraphicsExposures, &xgcvalues);
  332.  
  333.     xgcvalues.function = GXclear;
  334.     gc_erase = XCreateGC(display, win, GCForeground | GCBackground |
  335.         GCFont | GCGraphicsExposures | GCFunction, &xgcvalues);
  336.  
  337.     xgcvalues.function = GXxor;    /* Exclusive or */
  338.     xgcvalues.foreground = WhitePixel(display, screen_num);
  339.     xgcvalues.background = BlackPixel(display, screen_num);
  340.  
  341.     gc_xor = XCreateGC(display, win, GCForeground | GCBackground |
  342.         GCFont | GCGraphicsExposures | GCFunction, &xgcvalues);
  343.  
  344.  
  345.     /* Create our icon for when the window is closed */
  346.  
  347.     if  (!(icon_image = XCreateBitmapFromData(display, win,
  348.         blockbuster_bits,blockbuster_width, blockbuster_height)))
  349.     {
  350.         fprintf(stderr, "Can't create icon pixmap\n");
  351.         exit (1);
  352.     }
  353.  
  354.     size_hints.flags = PMinSize;
  355.     size_hints.x = 0;
  356.     size_hints.y = 0;
  357.     size_hints.height = STAGE_HEIGHT_IN_PIXELS;
  358.     size_hints.min_height = STAGE_HEIGHT_IN_PIXELS;
  359.     size_hints.width = STAGE_WIDTH_IN_PIXELS;
  360.     size_hints.min_width = STAGE_WIDTH_IN_PIXELS;
  361.  
  362.     wm_hints.flags = InputHint | IconPixmapHint;
  363.     wm_hints.input = True;
  364.     wm_hints.icon_pixmap = icon_image;
  365.  
  366.     class_hints.res_name = "XBlockbuster";
  367.     class_hints.res_class =  "XBlockbuster";
  368.  
  369.     XStringListToTextProperty(VersionList, 1, &VersionTextProp);
  370.     XSetWMProperties(display, win, &VersionTextProp, &VersionTextProp,
  371.         argv,argc, &size_hints, &wm_hints, &class_hints);
  372.  
  373.  
  374.     XMapWindow(display, win);
  375.     /* initialize random (used to determine next stage_nb) */
  376.     srand48( time( 0 ) );
  377.  
  378.     get_playground( argc, argv );
  379.  
  380.     /* and off we go */
  381.     bricks_init();
  382.     ball_init();
  383.     start_up(  );
  384.     ball1.quadrant = ball2.quadrant = ball3.quadrant = 0;
  385.  
  386.     event_handler();
  387. }
  388.